﻿using System.Drawing;
using System.Windows.Forms;

namespace PlusPlusPaint.Tools
{
    /// <summary>
    /// Base class for toolBuilders that want the usual features:  a preview, a brush,
    /// etc.
    /// </summary>
    abstract class StandardTool : ISketchTool
    {
        #region properties
        #region abstract properties
        /// <summary>
        /// True if the tool must be initially applied to an entirely new
        /// layer.
        /// </summary>
        public abstract bool DemandsNewLayer
        {
            get;
        }

        /// <summary>
        /// True if the tool is willing to work with a new layer.
        /// </summary>
        public abstract bool AcceptsNewLayer
        {
            get;
        }

        /// <summary>
        /// Returns true if the tool has become certain of what it intends to do.
        /// </summary>
        public bool Done
        {
            get;
            protected set;
        }
        #endregion

        public Image Preview
        {
            get;
            set;
        }

        public Color Colour
        {
            get;
            set;
        }

        public int BrushSize
        {
            get;
            set;
        }
        #endregion

        #region methods
        /// <summary>
        /// Given a layer, return true if willing to work on it.  It can be
        /// assumed that if a new layer was demanded, the layer will indeed be
        /// new (such excellent service!), and either empty, or provided by the
        /// SuggestNewLayer method of this tool
        /// </summary>
        public abstract bool AcceptableLayer(Layers.ILayer l);

        /// <summary>
        /// Create a layer that the tool in question is definitely willing to
        /// work on.
        /// </summary>
        public abstract Layers.ILayer SuggestNewLayer();

        /// <summary>
        /// Associates the tool with the given layer.  Should only be called by
        /// the layer in question, with itself as argument, once it has been
        /// established that everyone is okay with working together this way.
        /// </summary>
        public abstract void GiveAccessToLayer(Layers.VisualObjectLayer l, Point p);

        /// <summary>
        /// Associates the tool with the given layer.  Should only be called by
        /// the layer in question, with itself as argument, once it has been
        /// established that everyone is okay with working together this way.
        /// 
        /// There is a significant chance this function is never required;  in
        /// that case, it should be removed as soon as possible.
        /// </summary>
        public abstract void GiveAccessToLayer(Layers.CompositeLayer l, Point p);

        /// <summary>
        /// Do whatever has to be done when a mouse button is first pressed.
        /// </summary>
        public virtual void HandleMouseDown(MouseEventArgs mea) { }

        /// <summary>
        /// Do whatever has to be done when the mouse is moved while a mouse button
        /// is pressed.
        /// </summary>
        public virtual void HandleMouseDrag(MouseEventArgs mea) { }

        /// <summary>
        /// Do whatever has to be done when a mouse button is released.
        /// </summary>
        public virtual void HandleMouseUp(MouseEventArgs mea) { }

        /// <summary>
        /// Do whatever has to be done when a key is pressed.
        /// </summary>
        public virtual void HandleKeyPressed(KeyPressEventArgs kpea) { }
        #endregion
    }
}
